package com.stlm2.core.base.impl;

import com.stlm2.core.common.page.PageQueryParams;
import com.stlm2.core.common.page.PageView;
import com.stlm2.core.redis.RedisClient;
import net.sf.json.JSONObject;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * 集合持久层的公用的增，删，改，查类

 */
public abstract class BaseDaoImpl<T>{
	
	@Resource
	private SqlSessionTemplate sqlSession;


	public <E> E getMapper(Class<E> clazz){
		return sqlSession.getMapper(clazz);
	}


	public Logger getLogger(){
		Logger logger = LoggerFactory.getLogger(getClassName());
		
		return logger;
	}
	
	/**
	 * 
	 * 获取传过来的泛型类名字
	 * 
	 * @return
	 */
	public String getClassName() {
		Class<?> c = this.getClass();
		ParameterizedType pt = (ParameterizedType) c.getGenericSuperclass();
		Type[] types = pt.getActualTypeArguments();
		return ((Class<?>) types[0]).getName();
	}

	public void add(T t) {
		insert("add", t);
	}

	public void delete(Integer id) {
		delete("deleteById", id);
	}

	// 如果缓存中存在则从缓存直接获取
	// 如果缓存中没有则从数据库查询，并放入缓存
	@SuppressWarnings("unchecked")
	public T getById(Integer id) {
		// Gson gson = new Gson();
		//
		// String key = getClassName() + "_findById:" + id;
		// T result = redis.getRedisCacheInfo(key);
		// if(result == null){
		// result = (T)selectOne("getById", id);
		// if(result != null)
		// redis.setRedisCacheInfo(key, gson.toJson(result));
		// } else{
		// try {
		// result = (T) gson.fromJson((String)result,
		// Class.forName(getClassName()));
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
		// }
		//
		// return result;

		return selectOne("getById", id);
	}


	// 更新数据时，如果缓存中存在则同步更新
	public void modify(T t) {
		update("update", t);

		// try {
		// Class<?> clazz = t.getClass();
		// Method method = clazz.getMethod("getId");
		// if(method != null){
		// String key = getClassName() + "_findById:" + method.invoke(t);
		// boolean exists = redis.exists(key);
		// if(exists){
		// Gson gson = new Gson();
		// redis.setRedisCacheInfo(key, gson.toJson(t));
		// }
		// }
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
	}

	public List<T> query(PageView pageView, T t) {

		Map<String, Object> params = new PageQueryParams(pageView, t).getMap();

		return sqlSession.selectList(getClassName() + ".query", params);
	}
	public List<T> query1(PageView pageView,String selectId, T t) {

		Map<String, Object> params = new PageQueryParams(pageView, t).getMap();

		return sqlSession.selectList(getClassName() + "."+selectId, params);
	}

	public List<Map<String,Object>> query2(PageView pageView, T t) {

		Map<String, Object> params = new PageQueryParams(pageView, t).getMap();

		return sqlSession.selectList(getClassName() + ".query2", params);
	}
	public List<T> query3(PageView pageView, Map<String,Object> map) {

		Map<String, Object> params = new PageQueryParams(pageView, map).getMap();

		return sqlSession.selectList(getClassName() + ".query2", params);
	}

	public List<Map<String,Object>> query4(PageView pageView, T t) {

		Map<String, Object> params = new PageQueryParams(pageView, t).getMap();

		return sqlSession.selectList(getClassName() + ".query4", params);
	}

	//========自定义方法分页
	public List<T> query(PageView pageView, String selectId,  Object t) {
		Map<String, Object> params = new PageQueryParams(pageView, t).getMap();

		return sqlSession.selectList(getClassName() + "."+selectId,  params);
	}

	/**
	 * 查询list集合
	 * 
	 * @param first
	 * @param max
	 * @return
	 */
	public List<T> queryList(int first, int max, T t) {
		// List<T> list = selectList("query", params);
		//
		// if(list != null && first > 0 && max > 0){
		// int fromIndex = (first - 1) * max;
		// if(fromIndex > list.size())
		// fromIndex = list.size() - max;
		//
		// int toIndex = fromIndex + max;
		// if(toIndex > list.size())
		// toIndex = list.size();
		//
		// list = list.subList(fromIndex, toIndex);
		// }
		//
		// return list;

		return query(new PageView(first, max, false), t);
	}
	public List<Map<String,Object>> queryList2(int first, int max, T t) {
		// List<T> list = selectList("query", params);
		//
		// if(list != null && first > 0 && max > 0){
		// int fromIndex = (first - 1) * max;
		// if(fromIndex > list.size())
		// fromIndex = list.size() - max;
		//
		// int toIndex = fromIndex + max;
		// if(toIndex > list.size())
		// toIndex = list.size();
		//
		// list = list.subList(fromIndex, toIndex);
		// }
		//
		// return list;

		return query2(new PageView(first, max, false), t);
	}
	public List<T> queryList3(int first, int max, Map<String,Object> map) {
		// List<T> list = selectList("query", params);
		//
		// if(list != null && first > 0 && max > 0){
		// int fromIndex = (first - 1) * max;
		// if(fromIndex > list.size())
		// fromIndex = list.size() - max;
		//
		// int toIndex = fromIndex + max;
		// if(toIndex > list.size())
		// toIndex = list.size();
		//
		// list = list.subList(fromIndex, toIndex);
		// }
		//
		// return list;

		return query3(new PageView(first, max, false), map);
	}
	/**
	 * 分页查询 由于使用分页插件会执行两次SQL语句，第一次获得总条数，第二次获得分页数据
	 * 故将原先的查询简化为查询符合要求的所有数据，然后对其进行分页的封装
	 * 
	 * @return
	 */
	public PageView queryPageView(int pageNo, int pageSize, T t) {
		// PageView pageView = new PageView(pageNo, pageSize);
		// List<T> list = selectList("query", params);
		//
		// if(list != null){
		// pageView.setRowCount(list.size());
		//
		// int fromIndex = (pageView.getPageNow() - 1) * pageView.getPageSize();
		// if(fromIndex > list.size())
		// fromIndex = list.size() - pageView.getPageSize();
		//
		// int toIndex = fromIndex + pageView.getPageSize();
		// if(toIndex > list.size())
		// toIndex = list.size();
		//
		// list = list.subList(fromIndex, toIndex);
		// }
		// pageView.setRecords(list);
		//
		// return pageView;

		PageView pageView = new PageView(pageNo, pageSize, true);
		List<T> records = query(pageView, t);
		pageView.setRecords(records);
		return pageView;
	}
	public PageView queryPageView2(int pageNo, int pageSize, T t) {
		// PageView pageView = new PageView(pageNo, pageSize);
		// List<T> list = selectList("query", params);
		//
		// if(list != null){
		// pageView.setRowCount(list.size());
		//
		// int fromIndex = (pageView.getPageNow() - 1) * pageView.getPageSize();
		// if(fromIndex > list.size())
		// fromIndex = list.size() - pageView.getPageSize();
		//
		// int toIndex = fromIndex + pageView.getPageSize();
		// if(toIndex > list.size())
		// toIndex = list.size();
		//
		// list = list.subList(fromIndex, toIndex);
		// }
		// pageView.setRecords(list);
		//
		// return pageView;

		PageView pageView = new PageView(pageNo, pageSize, true);
		List<Map<String,Object>> records = query2(pageView, t);
		pageView.setRecords(records);
		return pageView;
	}
	public PageView queryPageView4(int pageNo, int pageSize, T t) {
		PageView pageView = new PageView(pageNo, pageSize, true);
		List<Map<String,Object>> records = query4(pageView, t);
		pageView.setRecords(records);
		return pageView;
	}
	//========自定义方法分页
	public PageView queryPageView(int pageNo, int pageSize, String selectId, Object t) {
		PageView pageView = new PageView(pageNo, pageSize, true);
		List<T> records = query(pageView,selectId,t);
		pageView.setRecords(records);
		return pageView;
	}
	//===自定义分页fl


	public List<T> queryAll() {
		return sqlSession.selectList(getClassName() + ".queryAll");
	}

	// 以下为对一些常用方法的封装
	/**
	 * 插入数据
	 * 
	 * @param arg0
	 * @param arg1
	 * @return
	 */
	public int insert(String arg0, Object arg1) {
		int result = sqlSession.insert(getClassName() + "." + arg0, arg1);
		
//		getLogger().warn(getUserName() + ":add object " + getId(arg1));
		
		return result;
	}

	/**
	 * 删除数据
	 * 
	 * @param arg0
	 * @param arg1
	 */
	public void delete(String arg0, Object arg1) {
		sqlSession.delete(getClassName() + "." + arg0, arg1);
		
//		getLogger().warn(getUserName() + ":delete object " + arg1);
	}

	/**
	 * 更新数据
	 * 
	 * @param arg0
	 * @param arg1
	 */
	public void update(String arg0, Object arg1) {
		sqlSession.update(getClassName() + "." + arg0, arg1);
		
//		getLogger().warn(getUserName() + ":edit object " + getId(arg1));
	}

	/**
	 * 查询单挑数据，自定义返回类型
	 * 
	 * @param arg0
	 * @param arg1
	 * @return
	 */
	public Object _selectOne(String arg0, Object arg1) {
		return sqlSession.selectOne(getClassName() + "." + arg0, arg1);
	}

	/**
	 * 查询唯一数据
	 * 
	 * @param arg0
	 * @param arg1
	 * @return
	 */
	public T selectOne(String arg0, Object arg1) {
		return sqlSession.selectOne(getClassName() + "." + arg0, arg1);
	}

	/**
	 * 查询所有数据
	 * 
	 * @param arg0
	 * @param arg1
	 * @return
	 */
	public List<T> selectList(String arg0, Object arg1) {
		return sqlSession.selectList(getClassName() + "." + arg0, arg1);
	}
	
	/**
	 * 查询所有数据，自定义返回类型
	 * 
	 * @param arg0
	 * @param arg1
	 * @return
	 */
	public List _selectList(String arg0, Object arg1) {
		return sqlSession.selectList(getClassName() + "." + arg0, arg1);
	}
	
	

	
	/**
	 * 获得操作对象ID
	 * @return
	 */
	private long getId(Object object){
		try {
			Class<?> basicObj = Class.forName(object.getClass().getName());
			Method method = basicObj.getMethod("getId");
			if(method != null) {
				return (Long) method.invoke(object);
			}
		} catch (Exception e) {}
		
    	return -1;
	}

	public void addIntoRedis(T t,List<String> keyList) {
        //通过java反射机制动态获取泛型的真实类型
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
		Class c= (Class) pt.getActualTypeArguments()[0];//当前类的真实类型
		Class pc = c.getSuperclass();
		Field[] fields = pc.getDeclaredFields();//取得所有类成员变量
		for (Field f : fields) {
			f.setAccessible(true);
		}
        //获取到类的名称，做为redis中的表名字
		String[] ss = c.getName().split("\\.");
	    String entityName =	ss[ss.length-1];

		Map<String,Object> filedMap = new HashMap<String, Object>();
		for (int i = 0; i < fields.length; i++) {
			try {
				filedMap.put(fields[i].getName(),fields[i].get(t));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
             JedisPool pool=null;
		     Jedis jedis= null;
		try{
           //获取一个jedis对象
			 pool =RedisClient.getPool();
			 jedis= pool.getResource();
			//根据keyList将对象存入到reids中
			for(String s :keyList){
				String key = entityName+":"+s+":"+filedMap.get(s);
			//	jedis.set(key,filedMap.toString());
				jedis.set(key,new JSONObject().fromObject(filedMap).toString());
			}

		}catch (Exception e){
            e.printStackTrace();
		}finally {
			pool.returnResource(jedis);
		}

	}
	public void addIntoRedis(T t,String key) {
		//通过java反射机制动态获取泛型的真实类型
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
		Class c= (Class) pt.getActualTypeArguments()[0];//当前类的真实类型
		Class pc = c.getSuperclass();
		Field[] fields = pc.getDeclaredFields();//取得所有类成员变量
		for (Field f : fields) {
			f.setAccessible(true);
		}
		//获取到类的名称，做为redis中的表名字
		String[] ss = c.getName().split("\\.");
		String entityName =	ss[ss.length-1];

		Map<String,Object> filedMap = new HashMap<String, Object>();
		for (int i = 0; i < fields.length; i++) {
			try {
				filedMap.put(fields[i].getName(),fields[i].get(t));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		JedisPool pool=null;
		Jedis jedis= null;
		try{
			//获取一个jedis对象
			pool =RedisClient.getPool();
			jedis= pool.getResource();
			jedis.set(key,new JSONObject().fromObject(filedMap).toString());


		}catch (Exception e){
			e.printStackTrace();
		}finally {
			pool.returnResource(jedis);
		}

	}
    public T selectOneFromRedis(T t){
		//通过java反射机制动态获取泛型的真实类型
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
		Class c= (Class) pt.getActualTypeArguments()[0];//当前类的真实类型
		Class pc = c.getSuperclass();
		Field[] fields = pc.getDeclaredFields();//取得所有类成员变量
		for (Field f : fields) {
			f.setAccessible(true);
		}
		//获取到类的名称，做为redis中的表名字
		String[] ss = c.getName().split("\\.");
		String entityName =	ss[ss.length-1];

		//获取想要根据哪个字段来进行查询对象
		String paramName="";
		for (int i = 0; i < fields.length; i++) {
			try {
				if(!StringUtils.isEmpty(fields[i].get(t))&&!Integer.valueOf(0).equals(fields[i].get(t))){
						paramName=fields[i].getName()+":"+fields[i].get(t);
					}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
           String key = entityName+":"+paramName;

		JedisPool pool=null;
		Jedis jedis= null;
		try{
			//获取一个jedis对象
			pool =RedisClient.getPool();
			jedis= pool.getResource();
		//根据key 获取一个对象
	   String entityT = jedis.get(key);
			JSONObject obj = new JSONObject().fromObject(entityT);//将json字符串转换为json对象
			T c2 = (T)JSONObject.toBean(obj,t.getClass());
			return c2;
		}catch (Exception e){
			e.printStackTrace();
		}finally {
			pool.returnResource(jedis);
		}
		return  null;
	}

	public T selectOneFromRedis(T t,String key){
		JedisPool pool=null;
		Jedis jedis= null;
		try{
			//获取一个jedis对象
			pool =RedisClient.getPool();
			jedis= pool.getResource();
			//根据key 获取一个对象
			String entityT = jedis.get(key);
			JSONObject obj = new JSONObject().fromObject(entityT);//将json字符串转换为json对象
			T c2 = (T)JSONObject.toBean(obj,t.getClass());
			return c2;
		}catch (Exception e){
			e.printStackTrace();
		}finally {
			pool.returnResource(jedis);
		}
		return  null;
	}

	/*
	* sfy
	* 从redis中获取所有对象
	* */
	public List<T> listFromRedis(T t){
		List<T> list = new ArrayList<T>();//承接对象的list对象
		//通过java反射机制动态获取泛型的真实类型
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
		Class c= (Class) pt.getActualTypeArguments()[0];//当前类的真实类型
		Class pc = c.getSuperclass();
		Field[] fields = pc.getDeclaredFields();//取得所有类成员变量
		for (Field f : fields) {
			f.setAccessible(true);
		}
		//获取到类的名称，做为redis中的表名字
		String[] ss = c.getName().split("\\.");
		String entityName =	ss[ss.length-1];

		//获取想要根据哪个字段来进行查询对象
		String paramName="";
		for (int i = 0; i < fields.length; i++) {
			try {
				if(!StringUtils.isEmpty(fields[i].get(t))&&!Integer.valueOf(0).equals(fields[i].get(t))){
					paramName=fields[i].getName()+":"+fields[i].get(t);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		 String[] ss2  =paramName.split(":");
		 ss2[1]="*";
		 paramName = ss2[0]+":"+ss2[1];
		String key = entityName+":"+paramName;

		JedisPool pool=null;
		Jedis jedis= null;
		try{
			//获取一个jedis对象
			pool =RedisClient.getPool();
			jedis= pool.getResource();
			//KEYS
			Set keys = jedis.keys(key);//列出所有符合条件的key
			Iterator t1=keys.iterator() ;
			while(t1.hasNext()){
				Object obj1=t1.next();
				String entityT = jedis.get(obj1.toString());
				JSONObject obj = new JSONObject().fromObject(entityT);//将json字符串转换为json对象
				T c2 = (T)JSONObject.toBean(obj,t.getClass());
                 list.add(c2);
			}

		return  list;
		}catch (Exception e){
			e.printStackTrace();
		}finally {
			pool.returnResource(jedis);
		}
		return null;
	}

 public void deleteFromRedis(T t){
//通过java反射机制动态获取泛型的真实类型
		ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
		Class c= (Class) pt.getActualTypeArguments()[0];//当前类的真实类型
		Class pc = c.getSuperclass();
		Field[] fields = pc.getDeclaredFields();//取得所有类成员变量
		for (Field f : fields) {
			f.setAccessible(true);
		}
		//获取到类的名称，做为redis中的表名字
		String[] ss = c.getName().split("\\.");
		String entityName =	ss[ss.length-1];

		//获取想要根据哪个字段来进行查询对象
		String paramName="";
		for (int i = 0; i < fields.length; i++) {
			try {
				if(!StringUtils.isEmpty(fields[i].get(t))&&!Integer.valueOf(0).equals(fields[i].get(t))){
					paramName=fields[i].getName()+":"+fields[i].get(t);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		String[] ss2  =paramName.split(":");
		ss2[1]="*";
		paramName = ss2[0]+":"+ss2[1];
		String key = entityName+":"+paramName;

		JedisPool pool=null;
		Jedis jedis= null;
		try{
			//获取一个jedis对象
			pool =RedisClient.getPool();
			jedis= pool.getResource();
			//KEYS
			Set keys = jedis.keys(key);//列出所有符合条件的key
			Iterator t1=keys.iterator() ;
			while(t1.hasNext()){
				Object obj1=t1.next();
				 jedis.del(obj1.toString());
			}


		}catch (Exception e){
			e.printStackTrace();
		}finally {
			pool.returnResource(jedis);
		}

	}
	public List<T> queryList1(int first, int max,String selectId, T t) {

		return query1(new PageView(first, max, false),selectId, t);
	}

}
